<template>
  <view class="option-wrapper">
    <view class="title">
      {{ title }}<text>{{ tip }}</text>
    </view>
    <slot>
      <view class="button-wrapper" v-if="mode === 'button'">
        <view
          v-for="(item, index) in buttons"
          :key="index"
          class="button"
          :class="{ checked: item.checked }"
          @click="itemChecked(item)"
        >
          {{ item.label }}
        </view>
      </view>
      <input
        v-else-if="mode === 'input'"
        v-model="inputValue"
        :placeholder="placeholder"
        :type="inputType"
        class="input"
        @input="inputChange"
      />
      <template v-else-if="mode === 'dateRange'">
        <view class="row" @click="openDatePicker">
          <input
            v-model="beginDate"
            :placeholder="placeholder[0]"
            disabled
            class="input"
          />
          <text>~</text>
          <input
            v-model="endDate"
            :placeholder="placeholder[1]"
            disabled
            class="input"
          />
        </view>
      </template>
      <template v-else-if="mode === 'inputRange'">
        <view class="row">
          <input
            v-model="beginNum"
            :placeholder="placeholder[0]"
            :type="inputType"
            class="input"
            @input="numChange"
          />
          <text>~</text>
          <input
            v-model="endNum"
            :placeholder="placeholder[1]"
            :type="inputType"
            class="input"
            @input="numChange"
          />
        </view>
      </template>
    </slot>
  </view>

  <!-- 日期选择器 -->
  <PopupDatePicker
    ref="datePicker"
    range
    :long-time-btn="false"
    :start-time="beginDate"
    :end-time="endDate"
    @operate="dateChange"
  />
</template>

<script setup>
import { ref, watchEffect } from "vue";
import { map, get, forEach, filter, isEqual } from "lodash";
import PopupDatePicker from "@/components/popup/popup-bottom-datepicker/index.vue";

const props = defineProps({
  // v-model
  modelValue: [String, Number, Array],
  // 选项标题
  title: String,
  // 标题旁侧说明
  tip: String,
  // 选项组，格式为[{label:xxx,value:xxx}]
  options: Array,
  // 选项组文字取值key
  labelKey: {
    type: String,
    default: "label",
  },
  // 选项数据取值Key
  valueKey: {
    type: String,
    default: "value",
  },
  // 是否可多选
  multiple: Boolean,
  // 筛选项模式 button、input、dateRange、inputRange
  mode: {
    type: String,
    default: "button",
  },
  // 输入框提示内容
  placeholder: [String, Array],
  // 输入框输入类型
  inputType: {
    type: String,
    default: "text",
  },
});

const emits = defineEmits(["update:modelValue"]);

/* ------------ 筛选模式为button ------------ */
// 选项数据
const buttons = ref();

// 选项被选中时
function itemChecked(item) {
  if (props.multiple) {
    // 多选
    item.checked = !item.checked;
    emits(
      "update:modelValue",
      map(filter(buttons.value, ["checked", true]), (o) => o.value)
    );
  } else {
    // 单选
    forEach(buttons.value, (v) => {
      v.checked = v.value == item.value;
    });
    emits("update:modelValue", item.value);
  }
}

/* ------------ 筛选模式为input ------------ */
// 输入框内容
let inputValue = ref(null);

// 输入框内容改变时
function inputChange(e) {
  emits("update:modelValue", e.detail.value);
}

/* ------------ 筛选模式为dateRange ------------ */
// 日期范围
let beginDate = ref(null);
let endDate = ref(null);

// 日期选择器
const datePicker = ref(null);

// 打开日期选择器
function openDatePicker() {
  datePicker.value.show();
}

// 选择的日期发生变化时
function dateChange(data) {
  beginDate.value = data.startDate;
  endDate.value = data.endDate;
  emits("update:modelValue", [beginDate.value, endDate.value]);
}

/* ------------ 筛选模式为inputRange ------------ */
// 数字区间
let beginNum = ref(null);
let endNum = ref(null);

// 数字输入框内容改变时
function numChange() {
  emits("update:modelValue", [beginNum.value, endNum.value]);
}

/* --------- 初始化 ----------- */

// 初始化options
function init() {
  return map(props.options, (o) => {
    const value = get(o, props.valueKey);
    /**
     * 若value是数组，那么多选时modelValue是二维数组，反之为一维数组
     * 若value是数值，那么多选时modelValue是一维数组，反之为数值
     */
    const checked = props.multiple
      ? Array.isArray(value)
        ? filter(props.modelValue, (o) => isEqual(o, value)).length > 0
        : props.modelValue.includes(value)
      : props.modelValue == value;
    return {
      label: get(o, props.labelKey),
      value: value,
      checked: checked,
    };
  });
}

watchEffect(() => {
  // 按钮模式
  if (props.mode === "button") {
    buttons.value = init();
    return;
  }

  // 文本框模式
  if (props.mode === "input") {
    inputValue.value = props.modelValue;
    return;
  }

  // 日期范围模式
  if (props.mode === "dateRange") {
    if (!Array.isArray(props.modelValue)) {
      throw Error("类型为dateRange时，modelValue需为日期数组");
    }
    beginDate.value = props.modelValue[0];
    endDate.value = props.modelValue[1];
    return;
  }

  // 数字范围模式
  if (props.mode === "inputRange") {
    if (!Array.isArray(props.modelValue)) {
      throw Error("类型为inputRange时，modelValue需为Number数组");
    }
    beginNum.value = props.modelValue[0];
    endNum.value = props.modelValue[1];
    return;
  }
});
</script>

<style lang="scss" scoped>
.option-wrapper {
  margin-bottom: 40rpx;
  .title {
    height: 29rpx;
    line-height: 29rpx;
    font-size: 30rpx;
    font-weight: bold;
    color: $uni-text-color;
    margin-bottom: 30rpx;
    text {
      font-size: 26rpx;
      color: $uni-text-color-grey;
    }
  }

  .button-wrapper {
    display: flex;
    flex-wrap: wrap;
    margin-right: -16rpx;
    .button {
      width: 160rpx;
      height: 50rpx;
      line-height: 50rpx;
      text-align: center;
      background: #f2f2f2;
      border-radius: 10rpx;
      font-size: 20rpx;
      font-weight: 400;
      color: $uni-text-color;
      margin-right: 16rpx;
      margin-bottom: 10rpx;
      &.checked {
        background: url("https://jhl-pay.oss-cn-shenzhen.aliyuncs.com/agent/icon-button-selected.png")
          no-repeat center;
        background-size: contain;
        color: $uni-color-primary;
      }
    }
  }
  .row {
    display: flex;
    align-items: center;
    text {
      font-size: 14rpx;
      font-weight: 400;
      color: $uni-text-color-grey;
    }
  }
  .input {
    width: 337rpx;
    height: 50rpx;
    line-height: 50rpx;
    text-align: center;
    background: #f2f2f2;
    border-radius: 10rpx;
    font-size: 20rpx;
    font-weight: 400;
    color: $uni-text-color;
  }
  :deep(.input-placeholder) {
    color: $uni-text-color-grey;
  }
}
</style>
